<?php

namespace Biz\service\advertisement\spotlight;

use Biz\cache\advertisement\CActivitySpotlight;
use Doraemon\cache\UserCounter;
use Doraemon\model\Live\LiveRoom;
use Doraemon\pockets\constInterface\statSign\AutoPlatformModule;
use Doraemon\service\Follow;
use Doraemon\service\statSign\Basic;
use Doraemon\tools\BlockType;
use Doraemon\tools\HhzEnv;
use Doraemon\tools\ImgUrl;
use Doraemon\tools\Log;
use Hhzbeads\Img\ImageType;
use Think\Exception;

class SpotlightActivity implements Preparation
{

    private $uid = 0;
    private $wiki_id = 0;
    private $brandId;
    private $topicId;
    private $release_time = 0;
    private array $error_msg = [];
    private array $labels = [];
    private array $tips = [];
    private array $features = [];
    private array $barrage = [];
    private array $winners = [];
    private array $rank_config = [];
    private array $statsign = [];
    private $room_id = 0;
    private $elements = [];
    private $publishElements = [];
    private CActivitySpotlight $cache_handler;

    public function __construct(SpotlightConfig $config)
    {
        $this->uid = $config->getUid();
        $this->brandId = $config->getBrandId();
        $this->labels = $config->getLabels();
        $this->tips = $config->getTips();
        $this->release_time = $config->getReleaseTime();
        $this->features = $config->getFeatures();
        $this->barrage = $config->getBarrage();
        $this->topicId = $config->getTopicId();
        $this->winners = $config->getWinners();
        $this->wiki_id = $config->getWikiId();
        $this->room_id = $config->getRoomId();
        $this->cache_handler = $config->getCacheHandler();
        $this->rank_config = $config->getRankConfig();
        $this->statsign = $config->getStatsign();
        $this->elements = $config->getElements();
        $this->publishElements = $config->getPublishElements();
    }

    public function __destruct()
    {
        if ($this->error_msg) {
            Log::info("Spotlight debug", $this->error_msg);
            if (HhzEnv::isShopTest() || HhzEnv::isTest()) {
                $this->cache_handler::pushLog(implode("|", $this->error_msg));
            }
        }
    }

    public function wikiCard(): array
    {

        $wiki_info = \Biz\service\wiki\Wiki::getDetail($this->wiki_id, $this->uid);
        \Doraemon\service\statSign\Basic::readDbConf(true);
        return [
            'id' => $wiki_info['id'] ?? '0',
            'title' => $wiki_info['title'] ?? '',
            'ori_min_price' => $wiki_info['ori_min_price'] ?? '',
            'ori_max_price' => $wiki_info['ori_max_price'] ?? '',
            'cover_img' => $wiki_info['cover_img'] ?? '',
            'is_fav' => $wiki_info['is_fav'] ?? '',
            'top_statSign' => Basic::genStatSign($this->statsign['wiki'] ?? AutoPlatformModule::MODULE_PRODUCTS_SPOTLIGHT_PAGE_WIKI_CARD, [
                Basic::EXTEND_KEY_OBJ_ID => $this->wiki_id,
                Basic::EXTEND_KEY_POS => 'top',
            ]),
            'center_statSign' => Basic::genStatSign($this->statsign['wiki'] ?? AutoPlatformModule::MODULE_PRODUCTS_SPOTLIGHT_PAGE_WIKI_CARD, [
                Basic::EXTEND_KEY_OBJ_ID => $this->wiki_id,
                Basic::EXTEND_KEY_POS => 'center',
            ]),
        ];
    }

    public function liveCard(): array
    {
        $status = LiveRoom::STATUS_CLOSE;
        try {
            if ($this->room_id) $status = LiveRoom::get('live_status', ['id' => $this->room_id]);
            $this->error("用户[{$this->uid}]获取直播卡片");
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取直播卡片 error:" . $e->getMessage());
        }
        return [
            'room_id' => $this->room_id,
            'status' => (int)$status,
        ];
    }

    public function brandCard(): array
    {
        $isFollow = false;
        try {
            $brand_info = \Biz\service\brand\Brand::getBrandInfoById($this->brandId);
            $brand_uid = $brand_info['uid'] ?? 0;
            $isFollow = $this->uid ? Follow::getIsFollowed($brand_uid, $this->uid) : false;
            $user_counter = \Biz\service\brand\BrandHhzCard::getUserCounter($this->brandId, $brand_info['uid']);
            $this->error("用户[{$this->uid}]获取品牌卡片");
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取品牌卡片 error:" . $e->getMessage());
        }

        return [
            'uid' => $brand_uid ?? 0,
            'nick' => $brand_info['brand_name'] ?? '',
            'icon' => empty($brand_info["logo"]) ? '' : ImgUrl::getUrl(ImageType::APPTYPE_BIZ, $brand_info["logo"], ImageType::IMAGE_SIZE_SQ_PHONE),
            'liked' => intval($user_counter['user_like'] ?? 0),
            'counter' => intval($user_counter['liver_said'] ?? 0),
            'is_followed' => boolval($isFollow),
        ];

    }

    public function topicId()
    {
        return $this->topicId;
    }

    public function winners(): array
    {
        return $this->winners;
    }

    public function barrage(): array
    {
        $response = [];
        foreach ($this->barrage as $k => $v) {
            $response[] = [
                'id' => $k + 1,
                'name' => $v,
                'statSign' => '',
            ];
        }
        return $response;
    }

    public function releaseTime(): int
    {
        return $this->release_time;
    }

    protected function error($message = '')
    {
        $this->error_msg[] = $message;
    }

    public function likeFeatures($inputFeatures)
    {
        try {
            if (empty($this->uid)) throw new Exception('用户未登录,不允许给新品打call');
            if (is_scalar($inputFeatures)) $features = explode(',', $inputFeatures);
            if (is_array($inputFeatures)) $features = $inputFeatures;
            if (empty($features)) throw new Exception('用户[{$this->uid}]未选择新品功能');

            $like = 0;
            $map = array_flip($this->features);
            $features = array_filter($features);
            foreach ($features as $feature) {
                if (!isset($map[$feature])) {
                    $this->error("用户[{$this->uid}]选择非法新品功能[$feature]");
                    continue;
                }
                //计数
                $like |= $map[$feature];
            }
            //个人记录
            $selected = (int)$this->cache_handler::getUserLikeFeatures($this->uid);
            ($selected || $like) && $this->cache_handler::userLikeFeatures($this->uid, $like);
            $this->error("用户[{$this->uid}]给新品打call $inputFeatures");
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]给新品打call error:" . $e->getMessage());
            return false;
        }
    }

    public function open()
    {
        if (empty($this->uid)) {
            $this->error('用户未登录,不允许打开盒子');
            return false;
        }
        $rs = $this->cache_handler::open($this->uid);
        $this->error("用户[{$this->uid}]打开盒子,打开结果:$rs");
        return $rs;
    }

    public function subscribe()
    {
        if (empty($this->uid)) {
            $this->error('用户未登录,不允许订阅');
            return false;
        }
        $rs = $this->cache_handler::subscribe($this->uid);
        $this->error("用户[{$this->uid}]订阅,订阅结果:$rs");
        return $rs;
    }

    public function nextSubscribe()
    {
        if (empty($this->uid)) {
            $this->error('用户未登录,不允许订阅下次活动');
            return false;
        }
        $rs = $this->cache_handler::nextSubscribe($this->uid);
        $this->error("用户[{$this->uid}]订阅下次活动,订阅结果:$rs");
        return $rs;
    }

    public function notePool($page)
    {
        try {
            $list = \Doraemon\service\TopicActivityAnswer::joinAnswers($this->topicId, $page, $this->uid);
            $pool = $list[0] ?? [];
            \Doraemon\service\statSign\Basic::readDbConf(true);
            $pool = array_map(function ($v) {
                return [
                    'type' => BlockType::TYPE_PHOTO,
                    'photo' => $v,
                    'statSign' => Basic::genStatSign($this->statsign['note'] ?? AutoPlatformModule::MODULE_PRODUCTS_SPOTLIGHT_PAGE_NOTE, [
                        Basic::EXTEND_KEY_OBJ_ID => $v['photo_info']['id'] ?? '',
                    ])
                ];
            }, $pool);
            $this->error("用户[{$this->uid}]获取瀑布流第[{$page}]页");
            return ['list' => $pool, 'isOver' => $list[1] ?? 1];
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取瀑布流第[{$page}]页 error:" . $e->getMessage());
        }
    }


    public function showAllGuess($source = []): array
    {
        $rs = empty($source) ? $this->cache_handler::allGuess() : $source;
        if (PHP_SAPI === 'cli') echo implode("\t", ["uid", "新品猜一猜"]), PHP_EOL;
        $response = [];
        foreach ($rs as $uid => $selected) {
            $guess = [];
            foreach ($this->labels as $id => $name) {
                if ($selected & $id) $guess[] = $name;
            }
            if (PHP_SAPI === 'cli') echo implode("\t", [$uid, $guess ? implode(',', $guess) : '-']), PHP_EOL;
            $response[$uid] = $guess;
        }
        return $response;
    }

    public function showAllLikeFeatures($source = []): array
    {
        $rs = empty($source) ? $this->cache_handler::allLikeFeatures() : $source;
        if (PHP_SAPI === 'cli') echo implode("\t", ["uid", "新品打call"]), PHP_EOL;
        $response = [];
        foreach ($rs as $uid => $selected) {
            $features = [];
            foreach ($this->features as $id => $name) {
                if ($selected & $id) $features[] = $name;
            }
            if (PHP_SAPI === 'cli') echo implode("\t", [$uid, $features ? implode(',', $features) : '-']), PHP_EOL;
            $response[$uid] = $features;
        }
        return $response;
    }

    public function allLikeFeatures(): array
    {
        return $this->cache_handler::allLikeFeatures();
    }

    public function allSubscribe(): array
    {
        return $this->cache_handler::allSubscribe();
    }

    public function allNextSubscribe(): array
    {
        return $this->cache_handler::allNextSubscribe();
    }

    public function allOpen(): array
    {
        return $this->cache_handler::allOpen();
    }

    public function allCache(): array
    {
        return [
            'guess' => $this->cache_handler::allGuess(),
            'features' => $this->allLikeFeatures(),
            'subscribe' => $this->allSubscribe(),
            'nextSubscribe' => $this->allNextSubscribe(),
            'open' => $this->allOpen(),
            'guessRanking' => $this->cache_handler::guessRanking(),
            'log' => $this->cache_handler::allLog(),
        ];
    }

    public function getCacheHandler()
    {
        return $this->cache_handler;
    }

    public function clearAllCache()
    {
        $this->cache_handler::clearSubscribe();
        $this->cache_handler::clearGuess();
        $this->cache_handler::clearRanking();
        $this->cache_handler::clearLog();
        $this->cache_handler::clearOpen();
        $this->cache_handler::clearNextSubscribe();
        $this->cache_handler::clearLikeFeatures();
    }

    public function isSubscribe()
    {
        try {
            $rs = $this->uid && $this->cache_handler::isSubscribe($this->uid);
            $show = $rs ? 'true' : 'false';
            $this->error("用户[{$this->uid}]获取订阅状态[{$show}]");
            return $rs;
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取订阅状态 error:" . $e->getMessage());
        }
    }

    public function isNextSubscribe()
    {
        try {
            $rs = $this->uid && $this->cache_handler::isNextSubscribe($this->uid);
            $show = $rs ? 'true' : 'false';
            $this->error("用户[{$this->uid}]获取订阅下次活动状态[{$show}]");
            return $rs;
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取订阅下次活动状态 error:" . $e->getMessage());
        }
    }

    public function guess($labels)
    {
        if (empty($this->uid)) {
            $this->error('用户未登录,不允许选择标签');
            return false;
        }
        if (is_scalar($labels)) $labels = explode(',', $labels);
        if (empty($labels)) {
            $this->error("用户[{$this->uid}]未选择标签");
            return false;
        }

        if ($this->cache_handler::isGuess($this->uid)) {
            $this->error("用户[{$this->uid}]已经猜过一次");
            return false;
        }
        $guess = 0;
        $map = array_flip($this->labels);
        foreach ($labels as $label) {
            if (!isset($map[$label])) {
                $this->error("用户[{$this->uid}]选择非法标签[$label]");
                continue;
            }
            //计数
            $guess |= $map[$label];
            $this->cache_handler::guessRecord($label);
        }

        //个人记录
        $guess && $this->cache_handler::userGuess($this->uid, $guess);

        $this->error("用户[{$this->uid}]猜词,". implode(",", $labels));
    }

    public function tips(): array
    {
        return $this->tips;
    }

    public function formatPercent($value, $total)
    {
        $percent = 10;
        if ($total > 0 && $value > 0) {
            $percent = round($value/$total, 2) * 100;
            if ($percent < 1) {
                $percent = 1;
            }
            if ($percent > 100) {
                $percent = 100;
            }
        }
        return $percent;
    }

    public function guessRank()
    {
        $response = [];
        try {
            $ranking = $this->cache_handler::guessRanking();
            $total = $this->cache_handler::getGuessTotal();
            $necessary = $this->rank_config['necessary'] ?? ['双子舱', '超大上筒', 'UVC紫外线除菌', '负氧离子护理'];
            $allow = $this->rank_config['allow'] ?? ['操作智能', '离子柔烘', '减震平衡', '99.99%除菌率'];
            $allowed = $this->rank_config['allowed'] ?? true;
            $limit = $this->rank_config['limit'] ?? 0;
            foreach ($necessary as $name) {
                $value = $ranking[$name] ?? 0;
                $response[] = ['name'=> $name, 'percent' => $this->formatPercent($value, $total)];
            }

            foreach ($ranking as $name => $value) {
                if ($allowed && in_array($name, $allow)) {
                    $response[] = ['name'=> $name, 'percent' => $this->formatPercent($value, $total)];
                    $allowed = false;
                }
            }
            if ($allowed) $response[] = ['name'=> '操作智能', 'percent' => $this->formatPercent(0, $total)];

            $sort = array_column($response, 'percent');
            array_multisort($sort, SORT_DESC, $response);
            $response = array_map(function ($v) {
                $v['percent'] = $v['percent'] . '%';
                return $v;
            }, $response);
            if ($limit) $response = array_slice($response, 0, $limit);
            $this->error("用户[{$this->uid}]获取排行榜");
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取排行榜 error:" . $e->getMessage());
        }

        return $response;
    }

    public function isOpen()
    {
        try {
            $rs = $this->uid && $this->cache_handler::isOpen($this->uid);
            $show = $rs ? 'true' : 'false';
            $this->error("用户[{$this->uid}]获取打开盒子的状态[{$show}]");
            return $rs;
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取打开盒子的状态 error:" . $e->getMessage());
        }
    }

    public function isGuess()
    {
        try {
            $rs = $this->uid && $this->cache_handler::isGuess($this->uid);
            $show = $rs ? 'true' : 'false';
            $this->error("用户[{$this->uid}]获取竞猜状态[{$show}]");
            return $rs;
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取竞猜状态 error:" . $e->getMessage());
        }
    }

    public function likedFeatures(): array
    {
        $response = [];
        try {
            //获取用户的选择
            $selected = (int)$this->cache_handler::getUserLikeFeatures($this->uid);

            //格式化返回
            foreach ($this->features as $id => $name) {
                $response[] = [
                    'name' => $name,
                    'selected' => ($selected & $id) > 0
                ];
            }
            $this->error("用户[{$this->uid}]获取新品功能 [$selected]");
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取新品功能 error:" . $e->getMessage());
        }

        return $response;
    }

    public function guessLabels(): array
    {
        $response = [];

        try {
            //获取用户的选择
            $selected = (int)$this->cache_handler::getUserGuess($this->uid);

            //格式化返回
            foreach ($this->labels as $id => $name) {
                $response[] = [
                    'name' => $name,
                    'selected' => ($selected & $id) > 0
                ];
            }

            $this->error("用户[{$this->uid}]获取新品猜一猜");
        } catch (\Exception $e) {
            $this->error("用户[{$this->uid}]获取新品猜一猜 error:" . $e->getMessage());
        }

        return $response;
    }

    public function getElements()
    {
        return $this->elements;
    }

    public function getPublishElements()
    {
        return $this->publishElements;
    }

    public function getUid()
    {
        return $this->uid;
    }

    public function getRoomId()
    {
        return $this->room_id;
    }

    public function monitoring()
    {
        while (true) {
            try {
                if (PHP_SAPI === 'fpm-fcgi') ob_start();
                list(, $msg) = $this->cache_handler::popLog();
                $msg = explode("|", $msg);
                foreach ($msg as $v) {
                    if (PHP_SAPI === 'cli') echo $v, PHP_EOL;
                    if (PHP_SAPI === 'fpm-fcgi') echo $v, "<br/>";
                }
                if (PHP_SAPI === 'cli') echo "-------------------", PHP_EOL;
                    if (PHP_SAPI === 'fpm-fcgi') {
                    $content = ob_get_contents();
                    echo $content;
                }
            } catch (\Exception $e) {
                echo "error:", $e->getMessage(), PHP_EOL;
            }
        }
    }
}